/**
 **************************************************************************
 * @file     at32f403a_407_board.c
 * @version  v2.1.2
 * @date     2022-08-16
 * @brief    set of firmware functions to manage leds and push-button.
 *           initialize delay function.
 **************************************************************************
 *                       Copyright notice & Disclaimer
 *
 * The software Board Support Package (BSP) that is made available to
 * download from Artery official website is the copyrighted work of Artery.
 * Artery authorizes customers to use, copy, and distribute the BSP
 * software and its related documentation for the purpose of design and
 * development in conjunction with Artery microcontrollers. Use of the
 * software is governed by this copyright notice and the following disclaimer.
 *
 * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
 * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
 * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
 * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
 * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
 *
 **************************************************************************
 */

#include "at32f403a_407_board.h"

/** @addtogroup AT32F403A_407_board
 * @{
 */

/** @defgroup BOARD
 * @brief onboard periph driver
 * @{
 */

/* delay variable */
static __IO uint32_t fac_us;
static __IO uint32_t fac_ms;

/* delay macros */
#define STEP_DELAY_MS 50

/**
 * @brief  initialize uart
 * @param  baudrate: uart baudrate
 * @retval none
 */

void uart_print_init(uint32_t baudrate)
{
  gpio_init_type gpio_init_struct;

#if defined(__GNUC__) && !defined(__clang__)
  setvbuf(stdout, NULL, _IONBF, 0);
#endif

  /* enable the uart and gpio clock */
  crr_periph_clock_enable(CRR_UART5_PERIPH_CLOCK, TRUE);
  crr_periph_clock_enable(CRR_GPIOB_PERIPH_CLOCK, TRUE);
  crr_periph_clock_enable(CRR_IOMUX_PERIPH_CLOCK, TRUE);
  gpio_default_para_init(&gpio_init_struct);

  /* configure the uart tx pin */
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  gpio_init_struct.gpio_pins = GPIO_PINS_9;
  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  gpio_init(GPIOB, &gpio_init_struct);
  gpio_pin_remap_config(UART5_GMUX_0001, TRUE);
  /* configure uart param */
  usart_init(UART5, baudrate, USART_DATA_8BITS, USART_STOP_1_BIT);
  usart_transmitter_enable(UART5, TRUE);
  usart_enable(UART5, TRUE);
}

__attribute__((used)) int _write(int fd, char *buf, int size)
{
  int i;

  for (i = 0; i < size; i++)
  {

    while (usart_flag_get(UART5, USART_TDBE_FLAG) == RESET)
      ;
    usart_data_transmit(UART5, *buf++);
  }

  return size;
}

/**
 * @brief  initialize delay function
 * @param  none
 * @retval none
 */
void delay_init()
{
  /* configure systick */
  systick_clock_source_config(SYSTICK_CLOCK_SOURCE_AHBCLK_NODIV);
  fac_us = system_core_clock / (1000000U);
  fac_ms = fac_us * (1000U);
}

/**
 * @brief  inserts a delay time.
 * @param  nus: specifies the delay time length, in microsecond.
 * @retval none
 */
void delay_us(uint32_t nus)
{
  uint32_t temp = 0;
  SysTick->LOAD = (uint32_t)(nus * fac_us);
  SysTick->VAL = 0x00;
  SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
  do
  {
    temp = SysTick->CTRL;
  } while ((temp & 0x01) && !(temp & (1 << 16)));

  SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
  SysTick->VAL = 0x00;
}

/**
 * @brief  inserts a delay time.
 * @param  nms: specifies the delay time length, in milliseconds.
 * @retval none
 */
void delay_ms(uint16_t nms)
{
  uint32_t temp = 0;
  while (nms)
  {
    if (nms > STEP_DELAY_MS)
    {
      SysTick->LOAD = (uint32_t)(STEP_DELAY_MS * fac_ms);
      nms -= STEP_DELAY_MS;
    }
    else
    {
      SysTick->LOAD = (uint32_t)(nms * fac_ms);
      nms = 0;
    }
    SysTick->VAL = 0x00;
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
    do
    {
      temp = SysTick->CTRL;
    } while ((temp & 0x01) && !(temp & (1 << 16)));

    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
    SysTick->VAL = 0x00;
  }
}

/**
 * @brief  inserts a delay time.
 * @param  sec: specifies the delay time, in seconds.
 * @retval none
 */
void delay_sec(uint16_t sec)
{
  uint16_t index;
  for (index = 0; index < sec; index++)
  {
    delay_ms(500);
    delay_ms(500);
  }
}

/**
 * @}
 */

/**
 * @}
 */
